using System;
using System.Collections.Generic;
using System.Text;
using Sinacor.Infra.Service.Data;
using System.Data.Common;
using System.Data;
using Sinacor.Infra.Service.Security.Authorization;
using Sinacor.Infra.Service.Common;
using System.Linq;

namespace Sinacor.Servico.Bovespa.Corretagem.ResourceAccess
{
    /// <summary>
    /// Acesso a dados de verificações de políticas de corretagem
    /// </summary>
    public class VerificacaoPolitica : BaseResourceAccess
    {
        #region Construtor

        public VerificacaoPolitica()
            : base(AuthorizationContext.Current.CompanyId)
        {
        }

        #endregion

        #region Métodos

        /// <summary>
        /// Consulta lista de verificações de políticas de corretagem conforme filtro.
        /// </summary>
        /// <param name="entity"></param>
        public List<BusinessEntity.VerificacaoPolitica> ConsultarVerificacoesPoliticas(BusinessEntity.Parameter.FiltroVerificacaoPolitica entity)
        {
            List<BusinessEntity.VerificacaoPolitica> listaVerificacaoPolitica = null;
            List<BusinessEntity.TipoOperacaoVerificacao> listaTipoOperacaoVerificacao = null;
            StringBuilder sql = new StringBuilder();

            listaTipoOperacaoVerificacao = new TipoOperacaoVerificacao().ConsultarTiposOperacoes(new BusinessEntity.Parameter.FiltroTipoOperacaoVerificacao());

            using (DbCommand command = this.DataBase.GetSqlStringCommand(" "))
            {
                sql.AppendLine("SELECT");
                sql.AppendLine("    CD_POLITICA CodigoPolitica,");
                sql.AppendLine("    DT_INICIAL DataInicial,");
                sql.AppendLine("    CD_OPERADOR CodigoOperador,");
                sql.AppendLine("    CD_ASSESSOR CodigoAssessor,");
                sql.AppendLine("    CD_AGENTE CodigoAgente,");
                sql.AppendLine("    TP_MERCADO Mercado,");
                sql.AppendLine("    CD_CARLIQ Carteira,");
                sql.AppendLine("    CD_CODISI Ativo,");
                sql.AppendLine("    CD_TABELA CodigoTabelaPadrao,");
                sql.AppendLine("    CD_TABELA_BENEF CodigoTabelaBeneficio,");
                sql.AppendLine("    COD_NAT_OPRC NaturezaOperacao,");
                sql.AppendLine("    COD_TIPO_OPRC TipoOperacao");
                sql.AppendLine("FROM");
                sql.AppendLine("    TBOCORR_VERI");
                sql.AppendLine("WHERE 1 = 1");

                #region Filtro

                //Filtros Opcionais
                if (entity.CodigoPolitica.HasValue)
                {
                    sql.AppendLine("AND CD_POLITICA = :CodigoPolitica");
                    this.DataBase.AddInParameter(command, "CodigoPolitica", DbType.Int32, entity.CodigoPolitica);
                }

                if (entity.DataInicial.HasValue)
                {
                    sql.AppendLine("AND DT_INICIAL = :DataInicial");
                    this.DataBase.AddInParameter(command, "DataInicial", DbType.DateTime, entity.DataInicial);
                }

                if (entity.CodigoOperador.HasValue)
                {
                    sql.AppendLine("AND CD_OPERADOR = :CodigoOperador");
                    this.DataBase.AddInParameter(command, "CodigoOperador", DbType.Int32, entity.CodigoOperador);
                }

                if (entity.CodigoAssessor.HasValue)
                {
                    sql.AppendLine("AND CD_ASSESSOR = :CodigoAssessor");
                    this.DataBase.AddInParameter(command, "CodigoAssessor", DbType.Int32, entity.CodigoAssessor);
                }

                if (entity.CodigoAgente.HasValue)
                {
                    sql.AppendLine("AND CD_AGENTE = :CodigoAgente");
                    this.DataBase.AddInParameter(command, "CodigoAgente", DbType.Int32, entity.CodigoAgente);
                }

                if (entity.Mercado.HasValue)
                {
                    sql.AppendLine("AND TP_MERCADO = :Mercado");
                    this.DataBase.AddInParameter(command, "Mercado", DbType.String, EnumConverter.ToString<BusinessEntity.Enum.TipoMercado>(entity.Mercado.Value));
                }

                if (entity.Carteira.HasValue)
                {
                    sql.AppendLine("AND CD_CARLIQ = :Carteira");
                    this.DataBase.AddInParameter(command, "Carteira", DbType.Int32, entity.Carteira);
                }

                if (!string.IsNullOrEmpty(entity.Ativo))
                {
                    sql.AppendLine("AND CD_CODISI = :Ativo");
                    this.DataBase.AddInParameter(command, "Ativo", DbType.String, entity.Ativo);
                }

                if (entity.CodigoTabelaPadrao.HasValue)
                {
                    sql.AppendLine("AND CD_TABELA = :CodigoTabelaPadrao");
                    this.DataBase.AddInParameter(command, "CodigoTabelaPadrao", DbType.Int32, entity.CodigoTabelaPadrao);
                }

                if (entity.CodigoTabelaBeneficio.HasValue)
                {
                    sql.AppendLine("AND CD_TABELA_BENEF = :CodigoTabelaBeneficio");
                    this.DataBase.AddInParameter(command, "CodigoTabelaBeneficio", DbType.Int32, entity.CodigoTabelaBeneficio);
                }

                if (entity.NaturezaOperacao.HasValue)
                {
                    sql.AppendLine("AND COD_NAT_OPRC = :NaturezaOperacao");
                    this.DataBase.AddInParameter(command, "NaturezaOperacao", DbType.String, EnumConverter.ToString<BusinessEntity.Enum.NaturezaOperacao?>(entity.NaturezaOperacao));
                }

                if (entity.TipoOperacao != null && !string.IsNullOrEmpty(entity.TipoOperacao.Codigo))
                {
                    sql.AppendLine("AND COD_TIPO_OPRC = :TipoOperacao");
                    this.DataBase.AddInParameter(command, "TipoOperacao", DbType.String, entity.TipoOperacao.Codigo);
                }

                #endregion

                command.CommandText = sql.ToString();

                listaVerificacaoPolitica = this.FindAll<BusinessEntity.VerificacaoPolitica>(command, reader => new BusinessEntity.VerificacaoPolitica
                {
                    CodigoPolitica = reader.GetValue<int>("CodigoPolitica"),
                    DataInicial = reader.GetValue<DateTime>("DataInicial"),
                    CodigoOperador = (reader["CodigoOperador"] != DBNull.Value ? reader.GetValue<int?>("CodigoOperador") : null),
                    CodigoAssessor = (reader["CodigoAssessor"] != DBNull.Value ? reader.GetValue<int?>("CodigoAssessor") : null),
                    CodigoAgente = (reader["CodigoAgente"] != DBNull.Value ? reader.GetValue<int?>("CodigoAgente") : null),
                    Mercado = (reader["Mercado"] != DBNull.Value ? EnumConverter.Parse<BusinessEntity.Enum.TipoMercado?>(reader.GetValue<string>("Mercado")) : null),
                    Carteira = (reader["Carteira"] != DBNull.Value ? reader.GetValue<int?>("Carteira") : null),
                    Ativo = (reader["Ativo"] != DBNull.Value ? reader.GetValue<string>("Ativo") : String.Empty),
                    CodigoTabelaPadrao = (reader["CodigoTabelaPadrao"] != DBNull.Value ? reader.GetValue<int?>("CodigoTabelaPadrao") : null),
                    CodigoTabelaBeneficio = (reader["CodigoTabelaBeneficio"] != DBNull.Value ? reader.GetValue<int?>("CodigoTabelaBeneficio") : null),
                    NaturezaOperacao = (reader["NaturezaOperacao"] != DBNull.Value ? EnumConverter.Parse<BusinessEntity.Enum.NaturezaOperacao?>(reader.GetValue<string>("NaturezaOperacao")) : null),
                    TipoOperacao = (reader["TipoOperacao"] != DBNull.Value ? new BusinessEntity.TipoOperacaoVerificacao { Codigo = reader.GetValue<string>("TipoOperacao") } : null)
                });
            }

            listaVerificacaoPolitica.ForEach(item =>
                listaTipoOperacaoVerificacao.ForEach(tipoOperacao =>
                {
                    if (item.TipoOperacao.Codigo.Equals(tipoOperacao.Codigo))
                    {
                        item.TipoOperacao = tipoOperacao;
                    }
                })
            );

            return listaVerificacaoPolitica;
            
        }

        /// <summary>
        /// Exclui todas as verificações de um politica de corretagem.
        /// </summary>
        /// <param name="entity"></param>
        public void ExcluirTodasVerificacoesPolitica(BusinessEntity.Parameter.FiltroVerificacaoPolitica entity)
        {
            StringBuilder sql = new StringBuilder();

            sql.AppendLine("DELETE FROM TBOCORR_VERI");
            sql.AppendLine("WHERE");
            sql.AppendLine("    CD_POLITICA = :CodigoPolitica");
            sql.AppendLine("    AND DT_INICIAL = :DataInicial");

            using (DbCommand command = this.DataBase.GetSqlStringCommand(sql.ToString()))
            {
                this.DataBase.AddInParameter(command, "CodigoPolitica", DbType.Int32, entity.CodigoPolitica);
                this.DataBase.AddInParameter(command, "DataInicial", DbType.DateTime, entity.DataInicial);

                this.DataBase.ExecuteNonQuery(command);
            }
        }

        /// <summary>
        /// Duplica a lista de verificações para nova política de corretagem baseando-se em
        /// outra política de corretagem
        /// </summary>
        /// <param name="politicaOrigem"></param>
        /// <param name="politicaDestino"></param>
        public void DuplicarVerificacoesPolitica(BusinessEntity.Parameter.FiltroPoliticaCorretagemChave politicaOrigem, BusinessEntity.Parameter.FiltroPoliticaCorretagemChave politicaDestino)
        {
            StringBuilder sql = new StringBuilder();

            sql.AppendLine("INSERT INTO TBOCORR_VERI(");
            sql.AppendLine("SELECT CD_OPERADOR,");
            sql.AppendLine("TP_MERCADO,");
            sql.AppendLine(":PoliticaDestinoCodigo,");
            sql.AppendLine(":PoliticaDestinoDataInicial,");            
            sql.AppendLine("CD_ASSESSOR,");
            sql.AppendLine("CD_AGENTE,");
            sql.AppendLine("CD_CODISI,");
            sql.AppendLine("CD_CARLIQ,");            
            sql.AppendLine("CD_TABELA,");
            sql.AppendLine("CD_TABELA_BENEF,");
            sql.AppendLine("COD_NAT_OPRC,");
            sql.AppendLine("COD_TIPO_OPRC");
            sql.AppendLine("FROM");
            sql.AppendLine("    TBOCORR_VERI");
            sql.AppendLine("WHERE");
            sql.AppendLine("    CD_POLITICA = :PoliticaOrigemCodigo");
            sql.AppendLine("AND DT_INICIAL = :PoliticaOrigemDataInicial)");

            using (DbCommand command = this.DataBase.GetSqlStringCommand(sql.ToString()))
            {
                this.DataBase.AddInParameter(command, "PoliticaDestinoCodigo", DbType.Int32, politicaDestino.Codigo);
                this.DataBase.AddInParameter(command, "PoliticaDestinoDataInicial", DbType.DateTime, politicaDestino.DataInicial);
                this.DataBase.AddInParameter(command, "PoliticaOrigemCodigo", DbType.Int32, politicaOrigem.Codigo);
                this.DataBase.AddInParameter(command, "PoliticaOrigemDataInicial", DbType.DateTime, politicaOrigem.DataInicial);

                this.DataBase.ExecuteNonQuery(command);
            }
        }

        /// <summary>
        /// Inclui uma verificação de política de corretagem
        /// </summary>
        /// <param name="entity"></param>
        public void IncluirVerificacaoPolitica(BusinessEntity.VerificacaoPolitica entity)
        {
            StringBuilder sql = new StringBuilder();

            sql.AppendLine("INSERT INTO TBOCORR_VERI(");
            sql.AppendLine("    CD_POLITICA,");
            sql.AppendLine("    DT_INICIAL,");
            sql.AppendLine("    CD_OPERADOR,");
            sql.AppendLine("    CD_ASSESSOR,");
            sql.AppendLine("    CD_AGENTE,");
            sql.AppendLine("    TP_MERCADO,");
            sql.AppendLine("    CD_CARLIQ,");
            sql.AppendLine("    CD_CODISI,");
            sql.AppendLine("    CD_TABELA,");
            sql.AppendLine("    CD_TABELA_BENEF,");
            sql.AppendLine("    COD_NAT_OPRC,");
            sql.AppendLine("    COD_TIPO_OPRC)");
            sql.AppendLine("VALUES(");
            sql.AppendLine("    :CodigoPolitica,");
            sql.AppendLine("    :DataInicial,");
            sql.AppendLine("    :CodigoOperador,");
            sql.AppendLine("    :CodigoAssessor,");
            sql.AppendLine("    :CodigoAgente,");
            sql.AppendLine("    :Mercado,");
            sql.AppendLine("    :Carteira,");
            sql.AppendLine("    :Ativo,");
            sql.AppendLine("    :CodigoTabelaPadrao,");
            sql.AppendLine("    :CodigoTabelaBeneficio,");
            sql.AppendLine("    :NaturezaOperacao,");
            sql.AppendLine("    :TipoOperacao)");

            using (DbCommand command = this.DataBase.GetSqlStringCommand(sql.ToString()))
            {
                this.DataBase.AddInParameter(command, "CodigoPolitica", DbType.Int32, entity.CodigoPolitica);
                this.DataBase.AddInParameter(command, "DataInicial", DbType.DateTime, entity.DataInicial);
                this.DataBase.AddInParameter(command, "CodigoOperador", DbType.Int32, entity.CodigoOperador);
                this.DataBase.AddInParameter(command, "CodigoAssessor", DbType.Int32, entity.CodigoAssessor);
                this.DataBase.AddInParameter(command, "CodigoAgente", DbType.Int32, entity.CodigoAgente);
                this.DataBase.AddInParameter(command, "Mercado", DbType.String, EnumConverter.ToString<BusinessEntity.Enum.TipoMercado?>(entity.Mercado));
                this.DataBase.AddInParameter(command, "Carteira", DbType.Int32, entity.Carteira);
                this.DataBase.AddInParameter(command, "Ativo", DbType.String, entity.Ativo);
                this.DataBase.AddInParameter(command, "CodigoTabelaPadrao", DbType.Int32, entity.CodigoTabelaPadrao);
                this.DataBase.AddInParameter(command, "CodigoTabelaBeneficio", DbType.Int32, entity.CodigoTabelaBeneficio);
                this.DataBase.AddInParameter(command, "NaturezaOperacao", DbType.String, EnumConverter.ToString<BusinessEntity.Enum.NaturezaOperacao?>(entity.NaturezaOperacao));
                this.DataBase.AddInParameter(command, "TipoOperacao", DbType.String, entity.TipoOperacao != null ? entity.TipoOperacao.Codigo : null);

                this.DataBase.ExecuteNonQuery(command);
            }
        }

        /// <summary>
        /// Exclui uma verificação de politica de corretagem.
        /// </summary>
        /// <param name="entity"></param>
        public void ExcluirVerificacaoPolitica(BusinessEntity.VerificacaoPolitica entity)
        {
            StringBuilder sql = new StringBuilder();

            sql.AppendLine("DELETE FROM TBOCORR_VERI");
            sql.AppendLine("WHERE 1=1 ");
            if (entity.CodigoPolitica.HasValue)
                sql.AppendLine("    AND CD_POLITICA = :CodigoPolitica");
            else
                sql.AppendLine("    AND CD_POLITICA is null");

            if (entity.DataInicial.HasValue)
                sql.AppendLine("    AND DT_INICIAL = :DataInicial");
            else
                sql.AppendLine("    AND DT_INICIAL is null");

            if (entity.CodigoOperador.HasValue)
                sql.AppendLine("    AND CD_OPERADOR = :CodigoOperador");
            else
                sql.AppendLine("    AND CD_OPERADOR is null");

            if (entity.CodigoAssessor.HasValue)
                sql.AppendLine("    AND CD_ASSESSOR = :CodigoAssessor");
            else
                sql.AppendLine("    AND CD_ASSESSOR is null");

            if (entity.CodigoAgente.HasValue)
                sql.AppendLine("    AND CD_AGENTE = :CodigoAgente");
            else
                sql.AppendLine("    AND CD_AGENTE is null");

            if (entity.Mercado.HasValue)
                sql.AppendLine("    AND TP_MERCADO = :Mercado");
            else
                sql.AppendLine("    AND TP_MERCADO is null");

            if (entity.Carteira.HasValue)
                sql.AppendLine("    AND CD_CARLIQ = :Carteira");
            else
                sql.AppendLine("    AND CD_CARLIQ is null");

            if (!string.IsNullOrEmpty(entity.Ativo))
                sql.AppendLine("    AND CD_CODISI = :Ativo");
            else
                sql.AppendLine("    AND CD_CODISI is null");

            if (entity.CodigoTabelaPadrao.HasValue)
                sql.AppendLine("    AND CD_TABELA = :CodigoTabelaPadrao");
            else
                sql.AppendLine("    AND CD_TABELA is null");

            if (entity.CodigoTabelaBeneficio.HasValue)
                sql.AppendLine("    AND CD_TABELA_BENEF = :CodigoTabelaBeneficio");
            else
                sql.AppendLine("    AND CD_TABELA_BENEF is null");

            if (entity.NaturezaOperacao.HasValue)
                sql.AppendLine("    AND COD_NAT_OPRC = :NaturezaOperacao");
            else
                sql.AppendLine("    AND COD_NAT_OPRC is null");

            if (entity.TipoOperacao != null)
                sql.AppendLine("    AND COD_TIPO_OPRC = :TipoOperacao");
            else
                sql.AppendLine("    AND COD_TIPO_OPRC is null");

            using (DbCommand command = this.DataBase.GetSqlStringCommand(sql.ToString()))
            {
                if (entity.CodigoPolitica.HasValue)
                    this.DataBase.AddInParameter(command, "CodigoPolitica", DbType.Int32, entity.CodigoPolitica);
                if (entity.DataInicial.HasValue)
                    this.DataBase.AddInParameter(command, "DataInicial", DbType.DateTime, entity.DataInicial);
                if (entity.CodigoOperador.HasValue)
                    this.DataBase.AddInParameter(command, "CodigoOperador", DbType.Int32, entity.CodigoOperador);
                if (entity.CodigoAssessor.HasValue)
                    this.DataBase.AddInParameter(command, "CodigoAssessor", DbType.Int32, entity.CodigoAssessor);
                if (entity.CodigoAgente.HasValue)
                    this.DataBase.AddInParameter(command, "CodigoAgente", DbType.Int32, entity.CodigoAgente);
                if (entity.Mercado.HasValue)
                    this.DataBase.AddInParameter(command, "Mercado", DbType.String, EnumConverter.ToString<BusinessEntity.Enum.TipoMercado?>(entity.Mercado));
                if (entity.Carteira.HasValue)
                    this.DataBase.AddInParameter(command, "Carteira", DbType.Int32, entity.Carteira);
                if (!string.IsNullOrEmpty(entity.Ativo))
                    this.DataBase.AddInParameter(command, "Ativo", DbType.String, entity.Ativo);
                if (entity.CodigoTabelaPadrao.HasValue)
                    this.DataBase.AddInParameter(command, "CodigoTabelaPadrao", DbType.Int32, entity.CodigoTabelaPadrao);
                if (entity.CodigoTabelaBeneficio.HasValue)
                    this.DataBase.AddInParameter(command, "CodigoTabelaBeneficio", DbType.Int32, entity.CodigoTabelaBeneficio);
                if (entity.NaturezaOperacao.HasValue)
                    this.DataBase.AddInParameter(command, "NaturezaOperacao", DbType.String, EnumConverter.ToString<BusinessEntity.Enum.NaturezaOperacao?>(entity.NaturezaOperacao));
                if (entity.TipoOperacao != null)
                    this.DataBase.AddInParameter(command, "TipoOperacao", DbType.String, entity.TipoOperacao.Codigo);

                this.DataBase.ExecuteNonQuery(command);
            }
        }

        /// <summary>
        /// Verifica se existem referencias a verificações para uma tabela
        /// </summary>
        /// <param name="entity"></param>
        public bool VerificarExisteVerificacaoTabela(int? codigoTabela)
        {
            object obj = null;
            StringBuilder sql = new StringBuilder();

            sql.AppendLine("SELECT DECODE(COUNT(1),0,0,1) Existe");
            sql.AppendLine("FROM TBOCORR_VERI A");
            sql.AppendLine("WHERE A.CD_TABELA = :codigoTabela");
            sql.AppendLine("    OR A.CD_TABELA_BENEF = :codigoTabela");

            using (DbCommand command = this.DataBase.GetSqlStringCommand(sql.ToString()))
            {
                this.DataBase.AddInParameter(command, "codigoTabela", DbType.Int32, codigoTabela);

                obj = this.DataBase.ExecuteScalar(command);
            }

            return (Int32.Parse(obj.ToString()) != 0);
        }

        #endregion
    }
}